#include <malloc.h>
#include <memory.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include "ines.h"


static volatile Level level = -1;

static String levelText[] = {"DEBUG", "INFO", "WARN", "ERROR", "FATAL"};

static Level ines_log_init_level() {
    Level tmp = DEBUG;
    String str = getenv("--ines-log-level");
    //判断当前日志输出等级对应枚举
    if (str != NULL) {
        for (int i = 0; i < sizeof(levelText) / sizeof(String); ++i) {
            if (strcmp(levelText[i], str) == 0) {
                tmp = i;
                break;
            }
        }
    }
    return tmp;
}

static void format_date_time(String buffer, int length) {
    time_t now;
    time(&now);
    struct tm tm;
    localtime_r(&now, &tm);
    strftime(buffer, length, "%Y-%m-%d %H:%m:%S", &tm);
}

static void ines_log(Level tmp, String text, va_list argc) {
    if (level == -1) {
        level = ines_log_init_level();
    }
    if (level <= tmp) {
        ulong len = 100 + strlen(text);

        byte buf[100];
        byte template[len];
        memset(template, '\0', len);
        memset(buf, '\0', 100);
        format_date_time(buf, 100);
        FILE *output = stdout;
        if (tmp >= WARN) {
            output = stderr;
        }

        sprintf(template, "[%s] [%s] - %s\n", buf, levelText[tmp], text);
        vfprintf(output, template, argc);
    }
}

extern bool ines_debug_enable() {
    if (level == -1) {
        level = ines_log_init_level();
    }
    return level == DEBUG;
}

extern void ines_debug(String text, ...) {
    va_list argc;
    va_start(argc, text);
    ines_log(DEBUG, text, argc);
    va_end(argc);
}

extern void ines_info(String text, ...) {
    va_list argc;
    va_start(argc, text);
    ines_log(INFO, text, argc);
    va_end(argc);
}

extern void ines_warn(String text, ...) {
    va_list argc;
    va_start(argc, text);
    ines_log(WARN, text, argc);
    va_end(argc);
}

extern void ines_error(String text, ...) {
    va_list argc;
    va_start(argc, text);
    ines_log(ERROR, text, argc);
    va_end(argc);
}

extern void ines_fatal(String text, ...) {
    va_list argc;
    va_start(argc, text);
    ines_log(FATAL, text, argc);
    va_end(argc);
    exit(-1);
}


extern String ines_error_text(int err_code) {
    static String errMsg[] = {
            "Unknown rom file format.",
            "Unknown cartridge brand."
    };

    return errMsg[err_code - UNKNOWN_ROM_FILE_FORMAT];
}